/*
 * Project Name spring-boot-tools
 * File Name ConnectAction
 * Package Name com.huxiaosu.tools.cmpp.service.action
 * Create Time 2024/4/20
 * Create by name：liujie
 */
package com.huxiaosu.tools.cmpp.action;

import com.huxiaosu.tools.cmpp.utils.Length;
import com.huxiaosu.tools.cmpp.config.CmppGatewayClient;
import com.huxiaosu.tools.cmpp.enums.CommandId;
import com.huxiaosu.tools.cmpp.enums.ResponseStatus;
import com.huxiaosu.tools.cmpp.model.action.ConnectMsg;
import com.huxiaosu.tools.cmpp.model.action.ConnectRespMsg;
import com.huxiaosu.tools.cmpp.action.AbstractMessageAction;
import com.huxiaosu.tools.cmpp.utils.Constants;
import com.huxiaosu.tools.cmpp.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.mina.core.buffer.IoBuffer;
import org.springframework.stereotype.Component;

/**
 * 7.4.1.1 CMPP_CONNECT 消息定义（SP -> ISMG）
 *
 * @author liujie
 * @date 2024/4/20 11:15
 */
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
@Slf4j
@Component
public class ConnectAction extends AbstractMessageAction {

    @Override
    public CommandId getMessageCommandId() {
        return CommandId.CMPP_CONNECT;
    }

    @Override
    public String getMessageCommandName() {
        return CommandId.CMPP_CONNECT.name();
    }

    @Override
    public ConnectMsg readMessage(IoBuffer ioBuffer) {
        ConnectMsg msgConnect = new ConnectMsg();
        byte[] sourceAddr = new byte[Length.Connect.SOURCE_ADDR];
        ioBuffer.get(sourceAddr);
        msgConnect.setSourceAddr(new String(sourceAddr));
        byte[] aiByte = new byte[Length.Connect.AUTHENTICATOR_SOURCE];
        ioBuffer.get(aiByte);
        msgConnect.setAuthenticatorSource(aiByte);
        msgConnect.setVersion(ioBuffer.get());
        msgConnect.setTimestamp(ioBuffer.getInt());
        return msgConnect;
    }

    @Override
    public void execute() {
        log.info("< CMPP CONNECT ...>");
        Integer sequenceId = super.message.getSequenceId();
        ConnectMsg msgConnect = (ConnectMsg) super.message.getMessageHeader();
        if (msgConnect == null || msgConnect.getAuthenticatorSource() == null) {
            setResultMsg(ResponseStatus.MESSAGE_STRUCTURE_ERROR, sequenceId, new byte[] {});
            return;
        }
        // 校验认证数据
        String clientIp = super.message.getClientIp();
        CmppGatewayClient cmppGatewayClient = (CmppGatewayClient) super.cacheService.get(clientIp);
        if (cmppGatewayClient == null) {
            setResultMsg(ResponseStatus.ILLEGAL_SOURCE_ADDRESS, sequenceId, new byte[] {});
            return;
        }
        byte[] authenticatorSource = msgConnect.getAuthenticatorSource();
        String authenticatorSourceStr = Utils.bytes2Hex(authenticatorSource);
        int timestamp = msgConnect.getTimestamp();
        String sourceAddr = msgConnect.getSourceAddr();
        String clientSharedSecret = cmppGatewayClient.getSharedSecret();
        byte[] serverAuth = Utils.getAuthenticatorSource(sourceAddr, clientSharedSecret, timestamp + "");
        if (serverAuth == null) {
            setResultMsg(ResponseStatus.AUTH_ERROR, sequenceId, new byte[] {});
            return;
        }
        String sign = Utils.bytes2Hex(serverAuth);
        if (!sign.equals(authenticatorSourceStr)) {
            setResultMsg(ResponseStatus.AUTH_ERROR, sequenceId, new byte[] {});
            return;
        }
        byte version = msgConnect.getVersion();
        String gatewayClientVersion = cmppGatewayClient.getVersion();
        if (!gatewayClientVersion.equals(String.valueOf(version))) {
            setResultMsg(ResponseStatus.VERSION_TOO_HIGH, sequenceId, new byte[] {});
            return;
        }

        byte[] authenticatorISMG = Utils.getAuthenticatorISMG(ResponseStatus.SUCCESS.getStatus(),
                authenticatorSourceStr, clientSharedSecret);
        setResultMsg(ResponseStatus.SUCCESS, super.message.getSequenceId(), authenticatorISMG);

    }

    private void setResultMsg(ResponseStatus status, Integer sequenceId, byte[] authenticatorISMG) {
        ConnectRespMsg connectResp = new ConnectRespMsg();
        // 消息总长度，总字节数:4+4+4(消息头)+6+16+1+4(消息主体)
        connectResp.setTotalLength(CommandId.CMPP_CONNECT_RESP.getMsgLength());
        // 标识创建连接
        connectResp.setCommandId(CommandId.CMPP_CONNECT_RESP.getCommand());
        // 序列，由我们指定
        connectResp.setSequenceId(sequenceId);
        connectResp.setStatus(status.getStatus());
        connectResp.setVersion(Constants.CMPP_VERSION);
        connectResp.setAuthenticatorISMG(authenticatorISMG);
        log.info("<Connect 响应消息{}>", connectResp);
        session.write(connectResp.toByte());
    }

}
